/**
 * JSON Schema 适配器
 * 将自定义 DSL 转换为符合 MCP 协议的 JSON Schema
 *
 * MCP 协议规范：
 * - 工具参数使用 JSON Schema Draft 2020-12
 * - 通过 JSON-RPC 2.0 传输
 * - inputSchema 应该是一个 JSON Schema 对象
 */

import type { DslSchema, FieldSchema, ToolMeta } from './tool-schema.js';

// JSON Schema 类型定义（符合 Draft 2020-12）
export interface JsonSchema {
  type?: 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object' | 'null';
  properties?: Record<string, JsonSchema>;
  items?: JsonSchema;
  required?: string[];
  additionalProperties?: boolean | JsonSchema;
  enum?: any[];
  const?: any;
  default?: any;
  description?: string;
  title?: string;

  // 字符串验证
  minLength?: number;
  maxLength?: number;
  pattern?: string;
  format?: string;

  // 数字验证
  minimum?: number;
  maximum?: number;
  exclusiveMinimum?: number;
  exclusiveMaximum?: number;
  multipleOf?: number;

  // 数组验证
  minItems?: number;
  maxItems?: number;
  uniqueItems?: boolean;

  // 对象验证
  minProperties?: number;
  maxProperties?: number;

  // 组合模式
  allOf?: JsonSchema[];
  anyOf?: JsonSchema[];
  oneOf?: JsonSchema[];
  not?: JsonSchema;
}

export class JsonSchemaAdapter {
  /**
   * 将 DSL FieldSchema 转换为 JSON Schema
   */
  private static fieldToJsonSchema(field: FieldSchema): JsonSchema {
    const schema: JsonSchema = {};

    // 设置基础类型
    switch (field.type) {
      case 'string':
        schema.type = 'string';
        if (field.minLength !== undefined) schema.minLength = field.minLength;
        if (field.maxLength !== undefined) schema.maxLength = field.maxLength;
        if (field.pattern) schema.pattern = field.pattern;
        break;

      case 'number':
        schema.type = 'number';
        // 优先使用 JSON Schema 标准命名，向后兼容 min/max
        const minValue = field.minimum ?? field.min;
        const maxValue = field.maximum ?? field.max;
        if (minValue !== undefined) schema.minimum = minValue;
        if (maxValue !== undefined) schema.maximum = maxValue;
        break;

      case 'boolean':
        schema.type = 'boolean';
        break;

      case 'array':
        schema.type = 'array';
        if (field.items) {
          schema.items = this.fieldToJsonSchema(field.items);
        }
        if (field.minLength !== undefined) schema.minItems = field.minLength;
        if (field.maxLength !== undefined) schema.maxItems = field.maxLength;
        break;

      case 'object':
        schema.type = 'object';
        if (field.properties && Object.keys(field.properties).length > 0) {
          schema.properties = {};
          const required: string[] = [];

          for (const [key, value] of Object.entries(field.properties)) {
            schema.properties[key] = this.fieldToJsonSchema(value);
            if (value.required !== false) {
              required.push(key);
            }
          }

          if (required.length > 0) {
            schema.required = required;
          }
        }
        // 默认允许额外属性，与 MCP 的灵活性保持一致
        schema.additionalProperties = true;
        break;

      case 'null':
        schema.type = 'null';
        break;

      case 'any':
      default:
        // 不设置 type，表示接受任意类型
        break;
    }

    // 处理枚举
    if (field.enum && field.enum.length > 0) {
      schema.enum = field.enum;
    }

    // 处理默认值
    if (field.default !== undefined) {
      schema.default = field.default;
    }

    // 添加描述
    if (field.description) {
      schema.description = field.description;
    }

    return schema;
  }

  /**
   * 将工具元数据转换为 JSON Schema (用于 MCP 协议)
   */
  static toolMetaToJsonSchema(meta: ToolMeta): JsonSchema {
    // 如果没有参数，返回空对象 schema
    if (!meta.parameters || Object.keys(meta.parameters).length === 0) {
      return {
        type: 'object',
        properties: {},
        additionalProperties: true,
      };
    }

    const jsonSchema: JsonSchema = {
      type: 'object',
      properties: {},
      additionalProperties: true,
    };

    const required: string[] = [];

    // 转换每个参数
    for (const [name, field] of Object.entries(meta.parameters)) {
      jsonSchema.properties![name] = JsonSchemaAdapter.fieldToJsonSchema(field);
      if (field.required !== false) {
        required.push(name);
      }
    }

    // 添加 required 数组
    if (required.length > 0) {
      jsonSchema.required = required;
    }

    return jsonSchema;
  }

  /**
   * 将工具的 DSL Schema 转换为 MCP 协议兼容的 JSON Schema
   *
   * MCP 协议期望的格式：
   * {
   *   "type": "object",
   *   "properties": {
   *     "param1": { "type": "string", "description": "..." },
   *     "param2": { "type": "number", "minimum": 0 }
   *   },
   *   "required": ["param1"],
   *   "additionalProperties": false
   * }
   */
  toJsonSchema(schema: DslSchema): JsonSchema {
    // 如果没有参数，返回空对象 schema
    if (!schema.properties || Object.keys(schema.properties).length === 0) {
      return {
        type: 'object',
        properties: {},
        additionalProperties: schema.additionalProperties !== false,
      };
    }

    const jsonSchema: JsonSchema = {
      type: 'object',
      properties: {},
      required: schema.required || [],
      additionalProperties: schema.additionalProperties === false ? false : true,
    };

    // 转换每个参数
    for (const [name, field] of Object.entries(schema.properties)) {
      jsonSchema.properties![name] = JsonSchemaAdapter.fieldToJsonSchema(field);
    }

    // 如果没有必需字段，删除 required 数组
    if (jsonSchema.required!.length === 0) {
      delete jsonSchema.required;
    }

    return jsonSchema;
  }

  /**
   * 验证参数是否符合 schema
   * 注意：这是一个简化的验证实现，实际的 MCP SDK 会使用完整的 JSON Schema 验证器
   */
  static validateAgainstSchema(
    data: any,
    schema: JsonSchema
  ): { valid: boolean; errors?: string[] } {
    const errors: string[] = [];

    // 类型检查
    if (schema.type) {
      const actualType = Array.isArray(data) ? 'array' : data === null ? 'null' : typeof data;

      if (actualType !== schema.type) {
        errors.push(`Expected type ${schema.type}, got ${actualType}`);
      }
    }

    // 对象验证
    if (schema.type === 'object' && typeof data === 'object' && data !== null) {
      // 检查必需字段
      if (schema.required) {
        for (const field of schema.required) {
          if (!(field in data)) {
            errors.push(`Missing required field: ${field}`);
          }
        }
      }

      // 检查属性
      if (schema.properties) {
        for (const [key, value] of Object.entries(data)) {
          if (key in schema.properties) {
            const propSchema = schema.properties[key];
            if (propSchema) {
              const result = this.validateAgainstSchema(value, propSchema);
              if (!result.valid) {
                errors.push(`Field '${key}': ${result.errors?.join(', ')}`);
              }
            }
          } else if (schema.additionalProperties === false) {
            errors.push(`Unexpected field: ${key}`);
          }
        }
      }
    }

    // 字符串验证
    if (schema.type === 'string' && typeof data === 'string') {
      if (schema.minLength !== undefined && data.length < schema.minLength) {
        errors.push(`String length ${data.length} is less than minimum ${schema.minLength}`);
      }
      if (schema.maxLength !== undefined && data.length > schema.maxLength) {
        errors.push(`String length ${data.length} exceeds maximum ${schema.maxLength}`);
      }
      if (schema.pattern) {
        const regex = new RegExp(schema.pattern);
        if (!regex.test(data)) {
          errors.push(`String does not match pattern: ${schema.pattern}`);
        }
      }
    }

    // 数字验证
    if (schema.type === 'number' && typeof data === 'number') {
      if (schema.minimum !== undefined && data < schema.minimum) {
        errors.push(`Value ${data} is less than minimum ${schema.minimum}`);
      }
      if (schema.maximum !== undefined && data > schema.maximum) {
        errors.push(`Value ${data} exceeds maximum ${schema.maximum}`);
      }
    }

    // 数组验证
    if (schema.type === 'array' && Array.isArray(data)) {
      if (schema.minItems !== undefined && data.length < schema.minItems) {
        errors.push(`Array length ${data.length} is less than minimum ${schema.minItems}`);
      }
      if (schema.maxItems !== undefined && data.length > schema.maxItems) {
        errors.push(`Array length ${data.length} exceeds maximum ${schema.maxItems}`);
      }
      if (schema.items) {
        for (let i = 0; i < data.length; i++) {
          const result = this.validateAgainstSchema(data[i], schema.items);
          if (!result.valid) {
            errors.push(`Item at index ${i}: ${result.errors?.join(', ')}`);
          }
        }
      }
    }

    // 枚举验证
    if (schema.enum && !schema.enum.includes(data)) {
      errors.push(`Value must be one of: ${schema.enum.join(', ')}`);
    }

    return {
      valid: errors.length === 0,
      errors: errors.length > 0 ? errors : undefined,
    };
  }
}
